/*
 * application.h
 *
 *  Created on: 17.01.2012
 *      Author: knz
 */

#ifndef APPLICATION_H_
#define APPLICATION_H_

// Заголовочные файлы STL должны быть вначале !!!
#include <list>
#include <map>
#include <fstream>

#include "socket.h"
#include "client-handler.h"
#include "app-mysql.h"

/** \brief Класс - приложение сервера
  *
  * Возможно создание только одного экземпляра данного класса. Это обеспечивается
  * private-конструктором и static функцией создания приложения createApplication().
  */
class Application {
public:
    //! \brief Единственный способ создания экземпляра приложения
    static Application* createApplication();
    //! \brief Правильный способ удаления экземпляра приложения
    static void deleteApplication();

    //! \brief Настройка основного сокета сервера
    bool serverInit(const char *pchDotAddress, int iPort);
    //! \brief Жизненный цикл приложения
    bool exec();

    // регистрируем клиент по идентификатору
    void registerClientId(int id, ClientHandler* pClient);
    bool sendMsg(int idSrc, int idDest, const std::string &sMsg);
    bool sendHistory(ClientHandler * pDest, int idHist);

    ClientHandler* getClientHandlerById(int id);
    ClientHandler* getClientHandlerByIp(std::string sClientIpAddress);

    virtual ~Application();
private:
    Application();

    // Серверный сокет, который будет открыт в неблокирующем режиме
    Socket *m_pServerSocket;
    // информацию по подключенным клиентам будем хранить в списке
    std::list<ClientHandler*> m_lsClientHandlers;
    std::map<std::string, ClientHandler*> m_mpClientHandlersByIp;
    std::map<int, ClientHandler*> m_mpClientHandlersById;

    // Объект управления базой данных приложения
    AppMySql *m_pDatabase;
    std::string m_sMySqlHostKey;
    std::string m_sMySqlUserKey;
    std::string m_sMySqlPasswordKey;
    std::string m_sMySqlDbNameKey;

    std::string m_sMySqlHost;
    std::string m_sMySqlUser;
    std::string m_sMySqlPassword;
    std::string m_sMySqlDbName;

    fd_set m_setRead;
    //! \brief Выполним select для сокета подключения клиентов и сокетов связи с клиентами
    int checkSocketsReadiness();
    //! \brief Разовая обработка сокетов клиентских подключений
    void makeUpSockets(bool *pbCanSleep);
    //! \brief Выполним задержку времени и передадим временной шаг БД плагинов
    void pollingPause(int ms);

    //! \brief Имя файла конфигурации приложения
    std::string m_sAppConfigFile;
    //! \brief Прочитать параметры конфигурации из файла в map
    bool readConfigFile(std::map<std::string, std::string> &mpParams);
    //! \brief Параметризовать приложение согласно данным прочитанного map
    void processParamsMap(std::map<std::string, std::string> &mpParams);
    //! \brief Создать файл конфигурации с параметрами по умолчанию
    bool createDefaultConfigFile();

};

extern Application *g_pApp;      // экземпляр приложения

#endif /* APPLICATION_H_ */
